<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Cache-Control" content="no-siteapp">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1, minimum-scale=1, maximum-scale=1">
<meta name="renderer" content="webkit">
<meta name="google" value="notranslate">
<meta name="robots" content="index,follow">


<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Akkuman">
<meta name="twitter:description" content="Akkuman的技术博客">
<meta name="twitter:image:src" content="http://127.0.0.1:8000/images/avatar.png">

<meta property="og:url" content="http://127.0.0.1:8000">
<meta property="og:title" content="Akkuman">
<meta property="og:description" content="Akkuman的技术博客">
<meta property="og:site_name" content="Akkuman">
<meta property="og:image" content="http://127.0.0.1:8000/images/avatar.png">
<meta property="og:type" content="website">
<meta name="robots" content="noodp">

<meta itemprop="name" content="Akkuman">
<meta itemprop="description" content="Akkuman的技术博客">
<meta itemprop="image" content="http://127.0.0.1:8000/images/avatar.png">

<link rel="canonical" href="http://127.0.0.1:8000">

<link rel="shortcut icon" href="/favicon.png">
<link rel="apple-itouch-icon" href="/favicon.png">

<link type="text/css" rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="/bundle/css/prism.css">
<link type="text/css" rel="stylesheet" href="/bundle/css/zoom.css">
<link type="text/css" rel="stylesheet" href="/bundle/css/main.css">
<script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>



<script>var cPlayers = [];var cPlayerOptions = [];</script>


<script type="text/javascript">
    var timeSinceLang = {
        year: '年前',
        month: '个月前',
        day: '天前',
        hour: '小时前',
        minute: '分钟前',
        second: '秒前'
    };
    var root = '';
</script>


        <meta name="keywords" content="逆向,">
        <meta name="description" content="逆向学习笔记（1）-为什么代码不停地循环运行">
        <meta name="author" content="Akkuman">
        <title>逆向学习笔记（1）-为什么代码不停地循环运行</title>
    </head>
    <body>
        
        <header id="header" class="clearfix">
  <div class="container-fluid">
      <div class="row">
          <div class="logo">
              <div class="header-logo">
                <script>
                  var getwbclass = function() {
                    var wbclass = ['b', 'w'];
                    return wbclass[Math.floor(Math.random()*wbclass.length)];
                  }
                  var sitetitle = "Akkuman";
                  for (i in sitetitle) {
                    document.write('<a href="/"><span class="' + getwbclass() + ' titlechar">' + sitetitle.charAt(i) + '</span></a>');
                  }          
                  
                </script>
                
                <a id="btn-menu" href="javascript:isMenu();">
                    <span class="b">·</span>
                </a>
                <a href="javascript:isMenu1();">
                    <span id="menu-1" class="bf">1</span>
                </a>
                <a href="javascript:isMenu2();">
                    <span id="menu-2" class="bf">2</span>
                </a>
                <a href="javascript:isMenu3();">
                    <span id="menu-3" class="bf">3</span>
                </a>
              </div>
              <div id="menu-page">
                <a href="/archive.html"><li>归档</li></a>
                <a href="/tag.html"><li>标签</li></a>
                
                <a href="/atom.xml"><li>订阅</li></a>
                
                <a href="about.html"><li>关于</li></a>
              </div>
              <div id="search-box">
                  <div id="search">
                      <input autocomplete="off" type="text" name="s" id="menu-search" placeholder="搜索..." data-root="" />
                  </div>
              </div>
          </div>
      </div>
  </div>
  </header>
        <div id="body" class="clearfix">
            <div class="container-fluid">
                <div class="row">
                    <div id="main" class="col-12 clearfix" role="main">
                        <article class="posti" itemscope itemtype="http://schema.org/BlogPosting">
                            <h1 class="post-title" itemprop="name headline">逆向学习笔记（1）-为什么代码不停地循环运行</h1>
                            <div class="post-meta">
                                <p>
                                    Written by <a itemprop="name" href="/about.me.html" rel="author">Akkuman</a> with ♥ on <time datetime="1489048387" itemprop="datePublished"></time> in <a href="/tag/%e9%80%86%e5%90%91/index.html">逆向 </a>
                                </p>
                            </div>
                            <div class="post-content" itemprop="articleBody">
                                <p>对于下面这段c语言代码会一直不停地循环，为什么呢？</p>

<pre><code class="language-c">#include&lt;stdio.h&gt;

void HelloWorld()
{
	int i = 0;
	int a[] = {1,2,3,4,5,6,7,8,9,10};
	for(i=0; i&lt;=10; i++)
	{
		a[i] = 0;
		printf(&quot;Hello World!\n&quot;);
	}
}

int main(int argc, char* argv[])
{
	HelloWorld();
	getchar();
	return 0;
}

</code></pre>

<h1>问题</h1>

<p>当你运行上面这串代码的时候，因为c语言并不会对数组越界进行检查，所以是不会报错可以直接运行的，那么是什么原因导致了下面这张图的结果呢？</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c11551a36ea.gif" alt="GIF.gif" /></p>

<h1>分析</h1>

<p>我们可以调试跟进看看，在HelloWorld函数上加一个断点跟进去看看</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c11956dee36.png" alt="snipaste_20170309_165830.png" /></p>

<p>这个函数主要的汇编代码如下</p>

<pre><code class="language-assembly">8:        int i = 0;
00401038   mov         dword ptr [ebp-4],0
9:        int a[] = {1,2,3,4,5,6,7,8,9,10};
0040103F   mov         dword ptr [ebp-2Ch],1
00401046   mov         dword ptr [ebp-28h],2
0040104D   mov         dword ptr [ebp-24h],3
00401054   mov         dword ptr [ebp-20h],4
0040105B   mov         dword ptr [ebp-1Ch],5
00401062   mov         dword ptr [ebp-18h],6
00401069   mov         dword ptr [ebp-14h],7
00401070   mov         dword ptr [ebp-10h],8
00401077   mov         dword ptr [ebp-0Ch],9
0040107E   mov         dword ptr [ebp-8],0Ah
10:       for(i=0; i&lt;=10; i++)
00401085   mov         dword ptr [ebp-4],0
0040108C   jmp         HelloWorld+77h (00401097)
0040108E   mov         eax,dword ptr [ebp-4]
00401091   add         eax,1
00401094   mov         dword ptr [ebp-4],eax
00401097   cmp         dword ptr [ebp-4],0Ah
0040109B   jg          HelloWorld+97h (004010b7)
11:       {
12:           a[i] = 0;
0040109D   mov         ecx,dword ptr [ebp-4]
004010A0   mov         dword ptr [ebp+ecx*4-2Ch],0
13:           printf(&quot;Hello World!\n&quot;);
004010A8   push        offset string &quot;Hello World!\n&quot; (0042301c)
004010AD   call        printf (004011a0)
004010B2   add         esp,4
14:       }
004010B5   jmp         HelloWorld+6Eh (0040108e)
15:   }
</code></pre>

<p>从<code>int i = 0;</code>开始看直到<code>for(i=0; i&lt;=10; i++)</code>的堆栈图是</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c11ad728904.png" alt="snipaste_20170309_170508.png" /></p>

<p>第一次进入循环开始先把0放到了[ebp-4]，然后跳到了<code>00401097   cmp dword ptr [ebp-4],0Ah</code>以及下面的jg，这里的意思是如果ebp-4中存放的值比0A大那么就执行<code>jg HelloWorld+97h (004010b7)</code>跳到004010b7函数结束
第一次进入循环时，cmp之后（ebp-4中存放的值比0A小）执行<code>0040109D</code>处的语句，此时<code>ECX</code>中的值变成了[ebp-4]中的值也就是0，然后<code>mov dword ptr [ebp+ecx*4-2Ch],0</code>将0放到<code>ebp+ecx*4-2Ch</code>处也就是<code>EBP-2C</code>处，下面的两条语句不用管是执行输出的，然后到了<code>add  esp,4</code>将栈顶的值加4，这里我们无需关注栈顶，然后<code>jmp HelloWorld+6Eh (0040108e)</code>跳回到<code>0040108e</code>继续执行</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c11e41e5384.png" alt="snipaste_20170309_170508.png" /></p>

<p>跳到<code>0040108E   mov  eax,dword ptr [ebp-4]</code>开始执行，紧接着这三条语句的作用是把<code>EBP-4</code>中的值加了1，也就是<code>EBP-4</code>中的值现在为1</p>

<pre><code class="language-assembly">mov eax,dword ptr [ebp-4]
add eax,1
mov dword ptr [ebp-4],eax
</code></pre>

<p>cmp比较之后再次执行循环体，循环体完成后再次跳到<code>0040108e</code>，此时<code>EBP-28</code>的值变为了0，栈顶esp再次增加了4（这个例子中栈顶是不用关注的）</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c11fe590ae4.png" alt="snipaste_20170309_172648.png" /></p>

<p>紧接着下次执行后</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c1202d748a0.png" alt="snipaste_20170309_172805.png" /></p>

<p>直到这个数组长度为10的数组执行到第十次</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c120f1a650e.png" alt="snipaste_20170309_173122.png" /></p>

<p>此时再次跳转到<code>0040108e</code>，然后<code>EBP-4</code>中的值再次增加了1，现在也就是<code>EBP-4</code>中的值变为了0A，cmp比较之后<code>EBP-4</code>中的值依旧不比0A大，接着执行<code>mov ecx,dword ptr [ebp-4]</code>，此时ECX的值变成了0A，接着执行<code>mov dword ptr [ebp+ecx*4-2Ch],0</code>也就是<code>mov dword ptr [ebp-4],0</code></p>

<p>然后呢，你发现了什么？？？就是他喵的<code>EBP-4</code>中的值变成了0</p>

<p><img src="" data-src="https://ooo.0o0.ooo/2017/03/09/58c12263d566e.png" alt="snipaste_20170309_173729.png" /></p>

<p>变成0代表着什么？？？<code>EBP-4</code>中的值是我们拿来干嘛的？是用来和0A进行cmp然后决定是否结束函数的，可是我们辛辛苦苦循环了10次，第11次全泡汤了，唯一的变化就是数组都成了0，栈顶的值变化了不少，然后再次cmp的时候，0和0A比，决定了你还是要循环，不管多少次，最后都会把你用来计数的地址<code>EBP-4</code>中的值清零</p>

<p>这也就是为什么上面这段c语言代码会一直不停地循环的原因</p>

<p><strong>转载请注明出处</strong></p>

                            </div>
                            <div style="display:block;" class="clearfix">
                                <section style="float:left;">
                                    <span itemprop="keywords" class="tags">
                                        tag(s): <a href="/tag/%e9%80%86%e5%90%91/index.html">逆向 </a>
                                    </span>
                                </section>
                                <section style="float:right;">
                                    <span><a id="btn-comments" href="javascript:isComments();">show comments</a></span> · <span><a href="javascript:goBack();">back</a></span> · 
                                    <span><a href="/">home</a></span>
                                </section>
                            </div>
                            



<div id="comments" class="gen">
    <script>
        document.write('<section id="disqus_thread"></section>');
        var site_comment_load = function disqus() {
            var d = document, s = d.createElement('script');
            s.src = '//Akkum4n.disqus.com/embed.js';
            s.setAttribute('data-timestamp', +new Date());
            (d.head || d.body).appendChild(s);
        }
    </script>
</div>

                        </article>
                    </div>
                </div>
            </div>
        </div>
        <footer id="footer" role="contentinfo">
    <div class="container-fluid">
        <div class="row">
        <div class="col-12">
            &copy; 
            <script type="text/javascript">
                document.write(new Date().getFullYear());
            </script>
            <a href="/">Akkuman</a>.
            Using <a target="_blank" href="http://www.chole.io/">Ink</a> & <a target="_blank" href="/">Story</a>.
        </div>
        </div>
    </div>
</footer>

<script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="/bundle/js/prism.js"></script>
<script src="/bundle/js/zoom-vanilla.min.js"></script>
<script src="/bundle/js/main.js"></script>

<script>
    window.onload=function(){
        if (window.location.hash!='') {
          var i=window.location.hash.indexOf('#comment');
          var ii=window.location.hash.indexOf('#respond-post');
          if (i != '-1' || ii != '-1') {
            document.getElementById('btn-comments').innerText='hide comments';
            document.getElementById('comments').style.display='block';
          }
        }
    }

    function isMenu(){
        if(document.getElementById('menu-1').style.display=='inline'||document.getElementById('menu-1').style.display=='block'){
            $('#search-box').fadeOut(200);
            $('#menu-page').fadeOut(200);
            $('#menu-1').fadeOut(500);
            $('#menu-2').fadeOut(400);
            $('#menu-3').fadeOut(300);
        } else {
            $('#menu-1').fadeIn(150);
            $('#menu-2').fadeIn(150);
            $('#menu-3').fadeIn(150);
        }
    }

    function isMenu1(){
        if(document.getElementById('menu-page').style.display=='block'){
            $('#menu-page').fadeOut(300);
        } else {
            $('#menu-page').fadeIn(300);
        }
    }

    function isMenu2(){
        if(document.getElementById('torTree')){
            if(document.getElementById('torTree').style.display=='block'){
                $('#torTree').fadeOut(300);
            } else {
                $('#torTree').fadeIn(300);
            }
        }
    }

    function isMenu3(){
        if(document.getElementById('search-box').style.display=='block'){
            $('#search-box').fadeOut(300);
        } else {
            $('#search-box').fadeIn(300);
        }
    }

    function isComments(){
        if(document.getElementById('btn-comments').innerText=='show comments'){
            document.getElementById('btn-comments').innerText='hide comments';
            document.getElementById('comments').style.display='block';
            site_comment_load();
        } else {
            document.getElementById('btn-comments').innerText='show comments';
            document.getElementById('comments').style.display='none';
        }
    }

    function Search404(){
        $('#menu-1').fadeIn(150);
        $('#menu-2').fadeIn(150);
        $('#menu-3').fadeIn(150);
        $('#search-box').fadeIn(300);
    }

    function goBack(){
        window.history.back();
    }
</script>


<script async>
"use strict";
(function(){
var cp = function(){
    var len = cPlayerOptions.length;
    for(var i=0;i<len;i++){
        var element = document.getElementById('player' + cPlayerOptions[i]['id'])
        while (element.hasChildNodes()) {
            element.removeChild(element.firstChild);
        };
        cPlayers[i] = new cPlayer({
            element: element,
            list: cPlayerOptions[i]['list'],
            });
    };
    cPlayers = [];cPlayerOptions = [];
};
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "https://cdn.bootcss.com/cplayer/3.2.1/cplayer.js";
script.async = true;
if(script.readyState){  
    script.onreadystatechange = function(){
        if (script.readyState == "loaded" ||
            script.readyState == "complete"){
            script.onreadystatechange = null;
            cp();
        }
    };
}else{  
    script.onload = function(){
        cp();
    };
}
document.head.appendChild(script);
})();
</script>

    </body>
</html>
